#include "mainwindow.h"
#include "draggablebutton.h"
#include "ui_mainwindow.h"
#include "xutil.h"
#include <hookhandler.h>
#include <windows.h>
#include <QCoreApplication>
#include <QDebug>
#include <QDesktopServices>
#include <QDir>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QFileIconProvider>
#include <QGraphicsDropShadowEffect>
#include <QGridLayout>
#include <QMessageBox>
#include <QMimeData>
#include <QProcess>
#include <QScreen>
#include <QStandardPaths>
#include <QString>
#include <QTimer>
#include <QUrl>

// 需要包含的 Windows 头文件
#include <objbase.h>
#include <shlobj.h>

void testAsync()
{
    qDebug() << "testAsync";
    QTimer::singleShot(0, []() {
        qDebug() << "timer singshot";
        testAsync();
    });
}

bool createDesktopShortcut(const QString &targetPath, const QString &shortcutName)
{
    // 初始化COM库
    if (FAILED(CoInitialize(NULL))) {
        qDebug() << "Failed to initialize COM library.";
        return false;
    }

    IShellLink *pShellLink = nullptr;
    IPersistFile *pPersistFile = nullptr;

    // 创建IShellLink对象
    HRESULT hr = CoCreateInstance(CLSID_ShellLink,
                                  NULL,
                                  CLSCTX_INPROC_SERVER,
                                  IID_IShellLink,
                                  (LPVOID *) &pShellLink);
    if (SUCCEEDED(hr)) {
        // 设置快捷方式的目标路径
        pShellLink->SetPath(QDir::toNativeSeparators(targetPath).toStdWString().c_str());
        // 可选：设置描述信息
        pShellLink->SetDescription(L"This is a shortcut created by Qt application.");

        // 查询IPersistFile接口
        hr = pShellLink->QueryInterface(IID_IPersistFile, (void **) &pPersistFile);
        if (SUCCEEDED(hr)) {
            // 获取桌面路径
            wchar_t desktopPath[MAX_PATH];
            if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, desktopPath))) {
                // 构建快捷方式的完整路径
                QString shortcutFullPath = QString::fromWCharArray(desktopPath) + "\\"
                                           + shortcutName + ".lnk";
                // 保存快捷方式到文件
                hr = pPersistFile
                         ->Save(QDir::toNativeSeparators(shortcutFullPath).toStdWString().c_str(),
                                TRUE);
                if (FAILED(hr)) {
                    qDebug() << "Failed to save the shortcut file.";
                }
                pPersistFile->Release();
            } else {
                qDebug() << "Failed to get Desktop folder path.";
            }
        } else {
            qDebug() << "Failed to get IPersistFile interface.";
        }
        pShellLink->Release();
    } else {
        qDebug() << "Failed to create IShellLink instance.";
    }

    CoUninitialize();
    return SUCCEEDED(hr);
}

//失败不知道为什么
void createNewDesktop()
{
    // 设置桌面名称
    //    LPCWSTR desktopName = L"MyNewDesktop";
    const wchar_t *desktopName = L"MyNewDesktop";

    // 创建桌面
    HDESK hNewDesktop = CreateDesktopW(desktopName,
                                       NULL,
                                       NULL,
                                       DESKTOP_CREATEWINDOW | DESKTOP_SWITCHDESKTOP,
                                       NULL,
                                       NULL

    );

    /*CreateDesktopExW(desktopName,
                                         NULL,                     // 设备名称
                                         NULL,                     // 显示模式
                                         DF_ALLOWOTHERACCOUNTHOOK, // 允许其他账户钩子
                                         0,                        // 安全描述符大小
                                         NULL,                     // 安全属性
                                         NULL,                     // 父桌面
                                         NULL                      // 保留参数
    );*/

    if (hNewDesktop == NULL) {
        qDebug() << "CreateDesktopExW failed. Error: " << GetLastError();
        return;
    }

    qDebug() << L"成功创建新桌面：" << desktopName;

    // 切换到新桌面
    if (!SwitchDesktop(hNewDesktop)) {
        qDebug() << "SwitchDesktop failed. Error: " << GetLastError();
        CloseDesktop(hNewDesktop);
        return;
    }

    qDebug() << L"已切换到新桌面";

    // 在新桌面上启动一个进程（例如记事本）
    STARTUPINFO si = {sizeof(STARTUPINFO)};
    si.lpDesktop = const_cast<LPWSTR>(desktopName);

    PROCESS_INFORMATION pi;

    if (!CreateProcess(NULL,           // 应用程序名
                       L"notepad.exe", // 命令行
                       NULL,           // 进程句柄不可继承
                       NULL,           // 线程句柄不可继承
                       FALSE,          // 不继承句柄
                       0,              // 无标志
                       NULL,           // 使用父进程环境
                       NULL,           // 使用父进程目录
                       &si,            // 指定桌面
                       &pi             // 输出信息
                       )) {
        qDebug() << "CreateProcess failed. Error: " << GetLastError();
        SwitchDesktop(GetThreadDesktop(GetCurrentThreadId())); // 回到原桌面
        CloseDesktop(hNewDesktop);
        return;
    }

    qDebug() << L"已在新桌面启动记事本";

    // 等待记事本关闭
    WaitForSingleObject(pi.hProcess, INFINITE);

    // 清理资源
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    // 切回原来的桌面
    HDESK hOriginalDesktop = GetThreadDesktop(GetCurrentThreadId());
    SwitchDesktop(hOriginalDesktop);

    // 关闭新桌面
    CloseDesktop(hNewDesktop);

    qDebug() << L"清理完成，回到原始桌面";
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow), wallpaperWidget(new WallperWidget),
      noteWidget(new NoteWidget), noteMapper(new NoteMapper)
{
    //OK run
    //    QString targetPath = "C:\\Windows\\notepad.exe"; // 目标程序路径
    //    QString shortcutName = "MyNotepadShortcut";      // 快捷方式名称

    //    if (createDesktopShortcut(targetPath, shortcutName)) {
    //        qDebug() << "快捷方式创建成功！";
    //    } else {
    //        qDebug() << "快捷方式创建失败！";
    //    }

    ui->setupUi(this);
    setWindowFlag(Qt::FramelessWindowHint);
    //1
    setWindowFlag(Qt::Tool); //设置所有窗口都不能关闭，进程退出，窗口才不会消失
    //透明效果不好看
    //    setAttribute(Qt::WA_TranslucentBackground);
    //2
    //    setAttribute(Qt::WA_ShowWithoutActivating);
    //    setWindowFlags(windowFlags() | Qt::WindowDoesNotAcceptFocus | Qt::ToolTip);
    //3
    //    setWindowFlags(windowFlags() | Qt::SplashScreen);
    //4
    //    setWindowFlags(windowFlags() | Qt::Window | Qt::WindowStaysOnTopHint);

    //    qDebug() << QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);

    //    setFixedSize(432,625);
    setFixedSize(size());
    //    QScreen *scr = QApplication::primaryScreen();
    //failed
    //    auto scr = screen();
    //    qDebug() << pos();
    //    qDebug() << y();
    //    qDebug() << mapToGlobal(pos());

    //    move(scr->availableSize().width() - width(), y());

    //    setAcceptDrops()
    //    setWindowFlag(Qt::WindowStaysOnBottomHint);
    //    setWindowFlag(Qt::WindowFullscreenButtonHint);//mac os
    //    setWindowFlag(Qt::WindowSystemMenuHint);//not work
    //    setWindowFlag(Qt::WindowCloseButtonHint); //no work
    //    wallpaperWidget->show();

    //Ok run
    //    startupAnimation();

    initTrayIcon();

    auto t = new QTimer(this);
    t->setInterval(1000);
    connect(t, &QTimer::timeout, [this]() {
        ui->noteAlarmClock->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
    });
    t->start();

    //    testAsync();//OK
    updateNoteContentLabel();

    connect(noteWidget, SIGNAL(newNoteIntoTable()), this, SLOT(updateNoteContentLabel()));

    //无效
    //    auto fsaw = ui->filesScrollArea->widget();
    //    fsaw->addAction(new QAction("act0", this));
    //    fsaw->addAction(new QAction("act1", this));
    //    fsaw->addAction(new QAction("act2", this));
    //    fsaw->addAction(new QAction("act3", this));
    //    fsaw->addAction(new QAction("act4", this));

    auto sw = ui->filesScrollArea->takeWidget();
    if (sw != nullptr) {
        sw->deleteLater();
    }
    auto filesw = new QWidget(this);
    ui->filesScrollArea->setWidget(filesw);

    auto fgl = new QGridLayout(filesw);
    filesw->setLayout(fgl);

    ui->filesScrollArea->setProperty("gridLayout", QVariant::fromValue(fgl));

    //    ui->filesScrollAreaWidgetContents->addAction()

    //    xlp(0, 100, [fgl, filesw](auto i) {
    //        fgl->addWidget(new QPushButton(QString("button%0").arg(i), filesw));
    //    });
    //    showAllFilesFromDesktop();

    // 启用鼠标跟踪以便捕获鼠标移动事件，即使没有按下鼠标按钮
    setMouseTracking(true);
    HookHandler::instance()->installHook();
    connect(HookHandler::instance(), &HookHandler::mouseMoved, [this](auto x, auto y) {
        //        qDebug() << "mouse pos:" << x << "," << y;
        auto src = screen();
        auto srcw = src->size().width();
        if (x > srcw - 10 && this->x() > srcw - this->width()) {
            move(srcw - width(), this->y());

        } else {
            if (this->x() >= srcw - width() && x < this->x()) {
                move(srcw, this->y());
            }
        }
    });

    //创建桌面失败！！！
    //    createNewDesktop();
}

MainWindow::~MainWindow()
{
    delete ui;
    delete wallpaperWidget;
    delete noteWidget;
    delete noteMapper;
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        auto p = event->globalPos();
        auto w = qApp->widgetAt(p);
        //        qDebug() << w;
        dragging = w == centralWidget() ? true : false;
        dragPosition = p - pos();
    }

    QMainWindow::mousePressEvent(event);
}

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    if (dragging && event->buttons() & Qt::LeftButton) {
        move(event->globalPos() - dragPosition);
    }
    QMainWindow::mouseMoveEvent(event);
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    dragging = false;
    QMainWindow::mouseReleaseEvent(event);
}

void MainWindow::startupAnimation()
{
    //    setAttribute(Qt::WA_TranslucentBackground);
    // 使用QGraphicsDropShadowEffect添加阴影
    //    QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect;
    //    shadow->setBlurRadius(20);
    //    shadow->setOffset(0, 0);
    //    shadow->setColor(QColor(0, 0, 0, 160));
    //    setGraphicsEffect(shadow);

    m_showAnimation = new QPropertyAnimation(this, "pos");
    m_showAnimation->setDuration(3000);
    m_showAnimation->setEasingCurve(QEasingCurve::OutQuad);

    m_showAnimation->setStartValue(QPoint(100, 100));
    m_showAnimation->setEndValue(QPoint(1000, 800));

    m_showAnimation->start();
}

void MainWindow::initTrayIcon()
{
    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(":/icon/tool.png"));

    QMenu *menu = new QMenu(this);
    menu->addAction("显示", this, [this]() {
        show();
        activateWindow();
    });
    menu->addAction("退出", this, &QApplication::quit);

    trayIcon->setContextMenu(menu);
    trayIcon->show();

    //    connect(trayIcon, &QSystemTrayIcon::activated, this, [this](auto reason){
    //        if(reason == QSystemTrayIcon::Trigger) showWindow();
    //    });

    //OK nice function
    // 显示气泡消息
    //    trayIcon->showMessage("应用程序", "已最小化到托盘", QSystemTrayIcon::Information, 1000);
    connect(trayIcon, &QSystemTrayIcon::activated, [this](auto s) {
        //        qDebug() << "activated" << s;
        if (s == QSystemTrayIcon::DoubleClick) {
            show();
            activateWindow();
        }
    });
}

//禁用关闭OK
//void MainWindow::closeEvent(QCloseEvent *e)
//{
//    if (trayIcon->isVisible()) {
//        hide();
//        e->ignore();
//    }
//}

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasText()) {
        //效果就是禁止符号消失，复制
        event->acceptProposedAction();
    }
    //    qDebug() << __FUNCTION__;
}

void MainWindow::dropEvent(QDropEvent *event)
{
    //    qDebug() << __FUNCTION__;
    if (event->mimeData()->hasText()) {
        QString buttonText = event->mimeData()->text();
        QPoint position = event->pos();

        //        qDebug() << buttonText;
        //        qDebug() << position;

        // 创建一个新的按钮
        //        DraggableButton *newButton = new DraggableButton(buttonText, this);
        //        newButton->move(position);

        //就用普通button
        //必须把file:///删除掉，否则拿不到图标
        QFileInfo fi(buttonText.mid(8));

        auto fn = fi.fileName();
        if (fn.endsWith(".exe") || fn.endsWith(".lnk")) {
            fn = fi.baseName();
        }

        auto icon = new DraggableButton(fn, this);
        icon->setProperty("filepath", buttonText);
        //        qDebug() << QFileIconProvider().icon(fi).name();
        icon->setIcon(QFileIconProvider().icon(fi));
        //        icon->setText(fn);
        //        icon->setIconSize(QSize(16, 16));

        //        icon->setFixedSize(QSize(100, 20));

        icon->setToolTip(fn);

        // 布局图标
        // ...
        auto glv = ui->filesScrollArea->property("gridLayout");
        auto gl = glv.value<QGridLayout *>();
        //        gl->setColumnMinimumWidth(0, 64);//failed
        gl->addWidget(icon);

        // 连接点击信号
        connect(icon, &DraggableButton::doubleClicked, [fi]() {
            //            qDebug() << __FUNCTION__;
            QDesktopServices::openUrl(QUrl::fromLocalFile(fi.filePath()));
        });

        event->acceptProposedAction();
    }
}

void MainWindow::showAllFilesFromDesktop()
{
    QString desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);

    QDir desktopDir(desktopPath);

    foreach (const QFileInfo &fileInfo,
             desktopDir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot)) {
        //        QPushButton *icon = new QPushButton(this);

        auto fn = fileInfo.baseName();
        auto icon = new DraggableButton(fn, this);

        icon->setIcon(QFileIconProvider().icon(fileInfo));

        //        qDebug() << fileInfo.baseName();
        //        qDebug() << fn.lastIndexOf(".");
        //        qDebug() << fn.left(fn.lastIndexOf("."));
        //        qDebug() << fn;
        //        icon->setText(fn);
        //        icon->setIconSize(QSize(16, 16));

        //        icon->setFixedSize(QSize(100, 20));

        icon->setToolTip(fn);

        // 布局图标
        // ...
        auto glv = ui->filesScrollArea->property("gridLayout");
        auto gl = glv.value<QGridLayout *>();
        gl->addWidget(icon);

        // 连接点击信号
        connect(icon, &DraggableButton::doubleClicked, [fileInfo]() {
            qDebug() << __FUNCTION__;
            QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.filePath()));
        });
    }
}

void MainWindow::updateNoteContentLabel()
{
    Note n = noteMapper->queryRecentNote(); //new note
    if (n.exists) {
        auto resetTimer = false;
        auto cnv = ui->noteContent->property("currentNote");
        if (cnv.isNull()) {
            ui->noteContent->setProperty("currentNote", QVariant::fromValue(n));
            resetTimer = true;
        } else {
            auto cn = cnv.value<Note>(); //old note
            if (n.id != cn.id) {
                //clear old timer
                cn.alarmTimer->stop();
                disconnect(cn.alarmTimer, nullptr, nullptr, nullptr);
                cn.alarmTimer->deleteLater();
                cn.alarmTimer = nullptr;
                ui->noteContent->setProperty("currentNote", QVariant::fromValue(n));
                resetTimer = true;
            }
        }
        if (resetTimer) {
            ui->noteContent->setText(n.content + "/" + n.alarmClock);
            ui->noteContent->setToolTip(n.content + "/" + n.alarmClock);
            auto wakeupTime = QDateTime::fromString(n.alarmClock, "yyyy-MM-dd hh:mm:ss");
            auto now = QDateTime::currentDateTime();
            qint64 differ = now.msecsTo(wakeupTime);
            QTimer *timer = new QTimer(this);
            //此处获取指针正合适，保存到控件私有数据里
            auto c = ui->noteContent->property("currentNote");
            auto note = c.value<Note>();
            note.alarmTimer = timer;
            ui->noteContent->setProperty("currentNote", QVariant::fromValue(note));

            //n.alarmTimer = timer;//这个是保存数据库的没意义

            timer->setSingleShot(true);
            timer->setInterval(differ);

            connect(timer, &QTimer::timeout, [this, n]() mutable {
                //无效代码，因为这个lambda已经执行了，获取sender已经没意义了
                //                auto c = ui->noteContent->property("currentNote");
                //                auto note = c.value<Note>();
                //                auto timer = qobject_cast<QTimer *>(sender());
                //                note.alarmTimer = timer;
                //                ui->noteContent->setProperty("currentNote", QVariant::fromValue(note));

                n.exists = true;
                n.past = true;
                noteMapper->saveNote(n);
                QMessageBox::information(this, "闹钟提醒", n.content);

                updateNoteContentLabel();
            });

            timer->start();
        }

    } else {
        ui->noteContent->setText("暂时没有提醒");
    }
}

void MainWindow::on_changeWallpaper_clicked()
{
    //    setWallpaperWithWinAPI("wallpaper/paper1.jpg");
    //    restoreDefaultWallpaper();
    //    QMessageBox::information(this, "open", "open execute");
    //    wallpaperWidget = new WallperWidget();
    wallpaperWidget->show();
    //    qDebug() << "changeWallpaper";
    //    this->close();
    //    auto w = new WallperWidget();
    //    w->show();
}

void MainWindow::on_calc_clicked()
{
    QProcess::startDetached("calc");
}

void MainWindow::on_pushButton_clicked()
{
    noteWidget->show();
}
